--在redis-cli中

--[[
eval的语法格式
EVAL script numkeys key [key ...] arg [arg ...]
    其中：
   <1> script：     你的lua脚本
   <2> numkeys:     key的个数
   <3> key:         redis中各种数据结构的替代符号
   <4> arg:         你的自定义参数

eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 username age hk 20
第一个参数的字符串是script，也就是lua脚本，2表示keys的个数，KEYS[1] 就是username的占位符, KEYS[2]就是
age的占位符，ARGV[1]就是jk的占位符，ARGV[2]就是20的占位符,以此类推，所以最后的结果应该就是:{return username age hk 20}
在cli中执行
250:0>eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 username age hk 20
 1)  "username"
 2)  "age"
 3)  "hk"
 4)  "20"

eval "return redis.call('set',KEYS[1],ARGV[1])" 1 foo bar

通常是执行lua脚本  key和value用一个逗号隔开
redis-cli --eval keys.lua k1 k2 , v1 v2
[root@centos1 lua]# redis-cli --eval keys.lua k1 k2 , v1 v2
1) 1) "k1"
   2) "k2"
2) "table"
3) "-----"
4) 1) "v1"
   2) "v2"
5) "table"


其中要要读写的键名应该作为key参数,其它的数据都作为arg参数
eval命令依据第二个参数将后面的所有参数分别存入脚本中KEYS和ARGV两个表类型的全局变量。
当脚本不需要任何参数时也不能省略这个参数(设为0)

evalsha

将Lua脚本加载到Redis服务端，得到该脚本的sha1校验和，evalsha命令使用sha1作为参数可以直接执行对应的Lua脚本，
避免每次发送Lua脚本的开销。这样客户端就不需要每次执行脚本内容，而脚本也会常驻在服务端，脚本内容得到了复用
加载脚本： script load命令可以将脚本内容加载到Redis内存中
[root@centos1 redis-lua]# redis-cli script load "$(cat hmgetall.lua)"
"032f22e507d134837f1c948f5b4f6b979b2e8beb"
得到sha1的值
在redis里执行脚本 
evalsha 脚本sha1值 key个数 key列表 参数列表
evalsha 032f22e507d134837f1c948f5b4f6b979b2e8beb 2 user:1 user:2 0

127.0.0.1:6379> evalsha 032f22e507d134837f1c948f5b4f6b979b2e8beb 2 user:1 user:2 
1) 1) "name"
   2) "hk"
   3) "age"
   4) "20"
2) 1) "name"
   2) "hk2"
   3) "age"
   4) "22"


Redis管理Lua脚本 
1.script load 
此命令用于将Lua脚本加载到Redis内存中 
2.script exists 
scripts exists sha1 [sha1 …] 
此命令用于判断sha1是否已经加载到Redis内存中 
3.script flush 
此命令用于清除Redis内存已经加载的所有Lua脚本,在执行script flush后,sha1不复存在。 
4.script kill 
此命令用于杀掉正在执行的Lua脚本。

使用Lua脚本的好处



为了防止某个脚本执行时间过长导致redis无法提供服务
redis提供lua-time-limit 参数限制脚本的最长运行时间,默认为5秒
当脚本运行超过这一限制后,redis将开始接收其它命令但不会执行(以确认脚本的原子性,因为此时脚本并没有终止),而是返回busy 错误
打开2个redis客户端
redis A> eval "while true do end" 0
redis B中
127.0.0.1:6379> keys *
(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
此时redis虽然可以接收任何命令,但实际会执行的只有2个 SCRIPT KILL or SHUTDOWN NOSAVE
127.0.0.1:6379> script kill
OK
需要注意的是 如果当执行的是修改操作,则 SCRIPT KILL 命令不会终止脚本的运行以防止脚本只执行了一部分(违背原子性的要求)
redis A>eval "redis.call('set','name','hk') while true do end" 0
redis B里

127.0.0.1:6379> keys *
(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
127.0.0.1:6379> script kill
(error) UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in a hard way using the SHUTDOWN NOSAVE command.

此时只能 SHUTDOWN NOSAVE
SHUTDOWN NOSAVE 不会进行持久化的操作 与  SHUTDOWN 的区别

]]
